<?php
// +—————————————————————————————————————————————————————————————————————
// | Created by Yunbao
// +—————————————————————————————————————————————————————————————————————
// | Copyright (c) 2013~2022 http://www.yunbaokj.com All rights reserved.
// +—————————————————————————————————————————————————————————————————————
// | Author: https://gitee.com/yunbaokeji
// +—————————————————————————————————————————————————————————————————————
// | Date: 2022-03-22
// +—————————————————————————————————————————————————————————————————————

/**
 * 支付回调
 */

namespace app\appapi\controller;
use cmf\controller\HomeBaseController;
use think\Db;

class PayController extends HomebaseController {
	
	
	//支付宝 回调
	public function notify_ali() {
        $configpri=getConfigPri();
		require_once(CMF_ROOT."sdk/alipay_app/alipay.config.php");
        //合作身份者id，以2088开头的16位纯数字
        $alipay_config['partner']		= $configpri['aliapp_partner'];
        
		require_once(CMF_ROOT."sdk/alipay_app/lib/alipay_core.function.php");
		require_once(CMF_ROOT."sdk/alipay_app/lib/alipay_rsa.function.php");
		require_once(CMF_ROOT."sdk/alipay_app/lib/alipay_notify.class.php");

		//计算得出通知验证结果
		$alipayNotify = new \AlipayNotify($alipay_config);
		$verify_result = $alipayNotify->verifyNotify();
		$this->logali("ali_data:".json_encode($_POST));
		if($verify_result) {//验证成功
			//商户订单号
			$out_trade_no = $_POST['out_trade_no'];
			//支付宝交易号
			$trade_no = $_POST['trade_no'];
			//交易状态
			$trade_status = $_POST['trade_status'];
			
			//交易金额
			$total_fee = $_POST['total_fee'];
			
			if($_POST['trade_status'] == 'TRADE_FINISHED') {

		
			}else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
	
	
				$orderinfo=Db::name('charge_user')->where("orderno='{$out_trade_no}' and money='{$total_fee}' and type='1'")->find();
				$this->logali("orderinfo:".json_encode($orderinfo));	
				if($orderinfo){
                    if($orderinfo['status']==0){
                        /* 更新会员虚拟币 */
                        $coin=$orderinfo['coin']+$orderinfo['coin_give'];
                        Db::name('user')->where("id='{$orderinfo['touid']}'")->setInc("coin",$coin);
                        /* 更新 订单状态 */
                        Db::name('charge_user')->where("id='{$orderinfo['id']}'")->update(array("status"=>1,"trade_no"=>$trade_no));
                        
                        /* 分销 */
                        setAgentProfit($orderinfo['touid'],$orderinfo['coin']);
                        
                        $this->sendGroupMsg($orderinfo);
                        $this->logali("orderno:".$out_trade_no."成功");
                    }else{
                        $this->logali("orderno:".$out_trade_no."已确认支付成功");
                    }

					echo "success";		
					exit;
				}else{
					$this->logali("orderno:".$out_trade_no.' 订单信息不存在');		
				}											
			}

			echo "fail";		
		}else {
			$this->logali("验证失败");		
			//验证失败
			echo "fail";

		}			
		
	}
	/* 支付宝支付 */
	
	/* 微信支付 */
    private $wxDate = null;
	public function notify_wx(){
		$configpri=getConfigPri();
		$xmlInfo=file_get_contents("php://input"); 

		//解析xml
		$arrayInfo = $this -> xmlToArray($xmlInfo);
		$this -> wxDate = $arrayInfo;
		$this -> logwx("wx_data:".json_encode($arrayInfo));//log打印保存
		if($arrayInfo['return_code'] == "SUCCESS"){
			if(isset($arrayInfo['return_msg']) && $arrayInfo['return_msg'] != null){
				echo $this -> returnInfo("FAIL","签名失败");
				$this -> logwx("签名失败:".$sign);//log打印保存
				exit;
			}else{
				$wxSign = $arrayInfo['sign'];
				unset($arrayInfo['sign']);
				$arrayInfo['appid']  =  $configpri['wx_appid'];
				$arrayInfo['mch_id'] =  $configpri['wx_mchid'];
				$key =  $configpri['wx_key'];
				ksort($arrayInfo);//按照字典排序参数数组
				$sign = $this -> sign($arrayInfo,$key);//生成签名
				$this -> logwx("数据打印测试签名signmy:".$sign.":::微信sign:".$wxSign);//log打印保存
				if($this -> checkSign($wxSign,$sign)){
					echo $this -> returnInfo("SUCCESS","OK");
					$this -> logwx("签名验证结果成功:".$sign);//log打印保存
					$this -> orderServer();//订单处理业务逻辑
					exit;
				}else{
					echo $this -> returnInfo("FAIL","签名失败");
					$this -> logwx("签名验证结果失败:本地加密：".$sign.'：：：：：三方加密'.$wxSign);//log打印保存
					exit;
				}
			}
		}else{
			echo $this -> returnInfo("FAIL","签名失败");
			$this -> logwx($arrayInfo['return_code']);//log打印保存
			exit;
		}			
	}
	
	private function returnInfo($type,$msg){
		if($type == "SUCCESS"){
			return $returnXml = "<xml><return_code><![CDATA[{$type}]]></return_code></xml>";
		}else{
			return $returnXml = "<xml><return_code><![CDATA[{$type}]]></return_code><return_msg><![CDATA[{$msg}]]></return_msg></xml>";
		}
	}		
	
	//签名验证
	private function checkSign($sign1,$sign2){
		return trim($sign1) == trim($sign2);
	}
	/* 订单查询加值业务处理
	 * @param orderNum 订单号	   
	 */
	private function orderServer(){
		$info = $this -> wxDate;
		$this->logwx("info:".json_encode($info));
		$orderinfo=Db::name('charge_user')->where("orderno='{$info['out_trade_no']}' and type='2'")->find();
		//$this->logwx("sql:".M()->getLastSql());
		$this->logwx("orderinfo:".json_encode($orderinfo));
		if($orderinfo){
            if($orderinfo['status']==0){
                /* 更新会员虚拟币 */
                $coin=$orderinfo['coin']+$orderinfo['coin_give'];
                Db::name('user')->where("id='{$orderinfo['touid']}'")->setInc("coin",$coin);
                /* 更新 订单状态 */
                Db::name('charge_user')->where("id='{$orderinfo['id']}'")->update(array("status"=>1,"trade_no"=>$info['transaction_id']));
                
                /* 分销 */
                setAgentProfit($orderinfo['touid'],$orderinfo['coin']);
                        
                $this->sendGroupMsg($orderinfo);
                $this->logwx("orderno:".$info['out_trade_no'].' 支付成功');
            }else{
                $this->logwx("orderno:".$info['out_trade_no'].' 已确认支付成功');
            }
		}else{
			$this->logwx("orderno:".$info['out_trade_no'].' 订单信息不存在');		
			return false;
		}		

	}		
	/**
	* sign拼装获取
	*/
	private function sign($param,$key){
		
		$sign = "";
		foreach($param as $k => $v){
			$sign .= $k."=".$v."&";
		}
	
		$sign .= "key=".$key;
		$sign = strtoupper(md5($sign));
		return $sign;
	
	}
	/**
	* xml转为数组
	*/
	private function xmlToArray($xmlStr){
		$msg = array(); 
		$postStr = $xmlStr; 
		$msg = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); 
		return $msg;
	}
	
	/* 微信支付 */

	/* 苹果支付 */
	
	public function notify_ios(){
		$content=file_get_contents("php://input");  
		$data = json_decode($content,true); 

        $this->logios("data:".json_encode($data));
        
		$receipt = $data["receipt-data"];     
		$version_ios = $data["version_ios"];
		
		$info = $this->getReceiptData($receipt, $version_ios);   
		
		$this->logios("info:".json_encode($info));
		
		$iforderinfo=Db::name('charge_user')->where("trade_no='{$info['transaction_id']}' and type='3'")->find();

		if($iforderinfo){
			echo '{"status":"fail","info":"非法提交-001"}';exit;
		}
        
        $chargeinfo=Db::name("charge_rules")->where("product_id='{$info['product_id']}'")->find();
        if(!$chargeinfo){
            echo '{"status":"fail","info":"非法提交-002"}';exit;
        }

        $out_trade_no = $data["out_trade_no"];
        
		//判断订单是否存在
		$orderinfo=Db::name('charge_user')->where("orderno='{$out_trade_no}' and coin='{$chargeinfo['coin_ios']}' and type='3'")->find();
        
		if($orderinfo){
            if($orderinfo['status']==0){
                /* 更新会员虚拟币 */
                $coin=$orderinfo['coin']+$orderinfo['coin_give'];
                Db::name('user')->where("id='{$orderinfo['touid']}'")->setInc("coin",$coin);
                /* 更新 订单状态 */
                Db::name('charge_user')->where("id='{$orderinfo['id']}'")->update(array("status"=>1,"trade_no"=>$info['transaction_id'],"ambient"=>$info['ambient']));
                
                /* 分销 */
                setAgentProfit($orderinfo['touid'],$orderinfo['coin']);
                        
                $this->sendGroupMsg($orderinfo);
                $this->logios("orderno:".$out_trade_no.' 支付成功');
            }else{
                $this->logios("orderno:".$out_trade_no.' 已确认支付成功');
            }
		}else{
			$this->logios("orderno:".$out_trade_no.' 订单信息不存在');
			echo '{"status":"fail","info":"订单信息不存在-003"}'; 		
			exit();
		}
		echo '{"status":"success","info":"充值支付成功"}';
		exit;
	}		
	public function getReceiptData($receipt, $version_ios){ 
	
        $config=getConfigPub();
        $this->logios("version_ios:".$version_ios);
        $this->logios("isSandboxc:".$config['ios_shelves']);
        $ambient=0;
		
		if ($version_ios == $config['ios_shelves']) {   
			//沙盒
			$endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt';
            $ambient=0;
		}else {  
			//生产
			$endpoint = 'https://buy.itunes.apple.com/verifyReceipt'; 
            $ambient=1;
		}   

		$postData = json_encode(   
				array('receipt-data' => $receipt)   
		);   

		$ch = curl_init($endpoint);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);	//关闭安全验证
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  	//关闭安全验证
		curl_setopt($ch, CURLOPT_POST, true);   
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);   

		$response = curl_exec($ch);   
		$errno    = curl_errno($ch);   
		$errmsg   = curl_error($ch);   
		curl_close($ch);   
        
        $this->logios("getReceiptData response:".json_encode($response));
        $this->logios("getReceiptData errno:".json_encode($errno));
        $this->logios("getReceiptData errmsg:".json_encode($errmsg));

		if($errno != 0) {   
			echo '{"status":"fail","info":"服务器出错，请联系管理员"}';
			exit;
		}   
		$data = json_decode($response,1);   

		if (!is_array($data)) {   
			echo '{"status":"fail","info":"验证失败,如有疑问请联系管理"}';
			exit;
		}   

		if (!isset($data['status']) || $data['status'] != 0) {   
			echo '{"status":"fail","info":"验证失败,如有疑问请联系管理"}';
			exit;
		}   

        $newdata=end($data['receipt']['in_app']);
		return array(     
			'product_id'     =>  $newdata['product_id'],   
			'transaction_id' =>  $newdata['transaction_id'],   
			'ambient' =>  $ambient,   
		);
	}   
		
	/* 苹果支付 */	
			
			
	//paypal支付 回调
	public function notify_paypal() {
		$content=file_get_contents("php://input");  
		$this->logpaypal("content:".$content);
		
		$
		
		
		
		$data=array();
		$content=explode("&",$content);
		foreach($content as $k=>$v){
			$v2=explode('=',$v);
			$data[$v2[0]]=$v2[1];
			
		}
		$this->logpaypal("data:".json_encode($data)); 

		require(CMF_ROOT.'sdk/paypal/PaypalIPN.php');
		
		$ipn = new \PaypalIPN();
		// Use the sandbox endpoint during testing.
		$configpri=getConfigPri();
		if($configpri['paypal_sandbox']!='1'){
			$ipn->useSandbox();
		}
		
		$verified = $ipn->verifyIPN();
		$this->logpaypal("verified:".json_encode($verified));
		if($verified) { //验证成功
			//支付宝交易号
			$trade_no = $data['txn_id'];
			$total_fee = $data['mc_gross'];
			$out_trade_no = $data['custom']; 
			
			$orderno_array=explode("_", $out_trade_no);
			
			//1充值钻石  2充值Vip
			if($orderno_array['2']==2){
				//判断订单是否存在----Vip充值
				$orderinfo=Db::name('vip_order')->where("orderno='{$out_trade_no}' and type='4'")->find();
				if($orderinfo){
					if($orderinfo['status']==0){
						/* 更新VIP */
						$length=$orderinfo['length'];
						$addtime=time();
						$vip=Db::name('vip_user')->where("uid={$orderinfo['uid']}")->find();
						if(!$vip){
							/* 未购买过 */
							$data=[
								'uid'=>$orderinfo['uid'],
								'addtime'=>$addtime,
								'endtime'=>$addtime + $length,
							];
							Db::name('vip_user')->insert($data);
						}else if($vip['endtime']< $addtime){
							/* 购买-已过期 */
							$data=[
								'addtime'=>$addtime,
								'endtime'=>$addtime + $length,
							];
							Db::name('vip_user')->where("uid={$orderinfo['uid']}")->update($data);
						}else{
							/* 续费 */
							$data=[
								'addtime'=>$addtime,
								'endtime'=>$vip['endtime'] + $length,
							];
							Db::name('vip_user')->where("uid={$orderinfo['uid']}")->update($data);
						}
						/* 更新 订单状态 */
						Db::name('vip_order')->where("id='{$orderinfo['id']}'")->update(array("status"=>1,"trade_no"=>$trade_no));
						
						/* 分销 */
						/* setAgentProfit($orderinfo['uid'],$orderinfo['coin']); */

						$this->logpaypal_vip("orderno:".$out_trade_no.' 支付成功');
						
						echo "success";		//请不要修改或删除
						// Reply with an empty 200 response to indicate to paypal the IPN was received correctly.
						header("HTTP/1.1 200 OK");
						exit;
						
					}else{
						$this->logpaypal_vip("orderno:".$out_trade_no.' 已确认支付成功');
					}
				}else{
					$this->logpaypal_vip("orderno:".$out_trade_no.' 订单信息不存在');
					//订单不存在
					echo "fail";
				}
				
			}else{
				//判断订单是否存在----钻石充值
				$orderinfo=Db::name('charge_user')->where("orderno='{$out_trade_no}' and type='4'")->find();
				if($orderinfo){
					if($orderinfo['status']==0){
						/* 更新会员虚拟币 */
						$coin=$orderinfo['coin']+$orderinfo['coin_give'];
						Db::name('user')->where("id='{$orderinfo['touid']}'")->setInc("coin",$coin);
						/* 更新 订单状态 */
						Db::name('charge_user')->where("id='{$orderinfo['id']}'")->update(array("status"=>1,"trade_no"=>$trade_no));
						
						/* 分销 */
						setAgentProfit($orderinfo['touid'],$orderinfo['coin']);
								
						$this->sendGroupMsg($orderinfo);
						
						
						$this->logpaypal("orderno:".$out_trade_no.' 支付成功');
					
						echo "success";		//请不要修改或删除
						// Reply with an empty 200 response to indicate to paypal the IPN was received correctly.
						header("HTTP/1.1 200 OK");
						exit;
					
						
					}else{
						$this->logpaypal("orderno:".$out_trade_no.' 已确认支付成功');
					}
				}else{
					$this->logpaypal("orderno:".$out_trade_no.' 订单信息不存在');
					//订单不存在
					echo "fail";
				}
				
			}
			
		
		}else {
			$this->logpaypal("验证失败");		
			//验证失败
			echo "fail";
			exit;
		}		
		
	}

			
			
			
	/* 充值成功 发送全站消息 */
	protected function sendGroupMsg($orderinfo){
        if($orderinfo){
            $userinfo=getUserInfo($orderinfo['uid']);
            
            $coin=$orderinfo['coin']+$orderinfo['coin_give'];
            $ext=[
                'method'=>'charge',
                'action'=>'0',
                'avatar'=>$userinfo['avatar'],
                'nickname'=>$userinfo['user_nickname'],
                'coin'=>(string)$coin,
            ];
            
            $configpri=getConfigPri();
            $group_id=$configpri['im_full_group_id'];
            $text_content=json_encode($ext);
            $receiver_id=null;
            $api=getTxRestApi();
            $ret = $api->group_send_group_system_notification($group_id, $text_content, $receiver_id);
            
            file_put_contents(CMF_ROOT.'log/sendGroupMsg_'.date('Y-m-d').'.txt',date('y-m-d H:i:s').'提交参数信息 text_content:'.json_encode($ext)."\r\n",FILE_APPEND);            
            file_put_contents(CMF_ROOT.'log/sendGroupMsg_'.date('Y-m-d').'.txt',date('y-m-d H:i:s').'提交参数信息 ret:'.json_encode($ret)."\r\n",FILE_APPEND);            
        }
	}	
    
    /* 打印log */
	protected function logali($msg){
		file_put_contents(CMF_ROOT.'log/paylog/logali_'.date('Y-m-d').'.txt',date('Y-m-d H:i:s').'  msg:'.$msg."\r\n",FILE_APPEND);
	}		
	/* 打印log */
	protected function logwx($msg){
		file_put_contents(CMF_ROOT.'log/paylog/logwx_'.date('Y-m-d').'.txt',date('Y-m-d H:i:s').'  msg:'.$msg."\r\n",FILE_APPEND);
	}			
	/* 打印log */
	protected function logios($msg){
		file_put_contents(CMF_ROOT.'log/paylog/logios_'.date('Y-m-d').'.txt',date('Y-m-d H:i:s').'  msg:'.$msg."\r\n",FILE_APPEND);
	}	
	/* 打印log */
	public function logpaypal($msg){
		file_put_contents(CMF_ROOT.'log/paylog/logpaypal_'.date('Y-m-d').'.txt',date('Y-m-d H:i:s').'  msg:'.$msg."\r\n",FILE_APPEND);
	}
	/* 打印log */
	protected function logpaypal_vip($msg){
		file_put_contents(CMF_ROOT.'log/paylog/viplogpaypal_'.date('Y-m-d').'.txt',date('Y-m-d H:i:s').'  msg:'.$msg."\r\n",FILE_APPEND);
	}

}


